-
-
Notifications
You must be signed in to change notification settings - Fork 108
feat: migration code fixer improvements for xUnit and NUnit #4367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Adds support for converting xUnit's Record.Exception() and
Record.ExceptionAsync() patterns to try-catch blocks during migration.
The conversion transforms:
```csharp
var ex = Record.Exception(() => SomeMethod());
```
To:
```csharp
Exception? ex = null;
try
{
SomeMethod();
}
catch (Exception e)
{
ex = e;
}
```
Fixes #4332
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add tests verifying that Assert.Throws<T>() with property access works correctly: - Assert_Throws_With_Property_Access_Can_Be_Converted: tests capturing exception and accessing properties like .ParamName - Assert_Throws_With_Message_Contains_Can_Be_Converted: tests using Assert.Contains with ex.Message Both tests pass, confirming issue #4334 is working correctly. Co-Authored-By: Claude Opus 4.5 <[email protected]>
Instead of removing the NUnit [Platform] attribute, convert it to TUnit's equivalent attributes: - [Platform(Include = "Win")] -> [RunOn(OS.Windows)] - [Platform(Exclude = "Linux")] -> [ExcludeOn(OS.Linux)] - [Platform(Include = "Win,Linux")] -> [RunOn(OS.Windows | OS.Linux)] Supports mapping NUnit platform strings to TUnit OS enum: - Win, Win32, Windows -> OS.Windows - Linux, Unix -> OS.Linux - MacOsX, MacOS, OSX, Mac -> OS.MacOs Unknown platforms are removed (cannot convert). Co-Authored-By: Claude Opus 4.5 <[email protected]>
SummaryThis PR adds NUnit Platform attribute conversion to RunOn/ExcludeOn and XUnit Record.Exception conversion to try-catch blocks for the migration code fixers. Critical IssuesNone found ✅ Suggestions1. NUnit Platform Attribute - Positional Argument BugIn if (argName == "Include" || argName == null)
{
// Named argument Include= or positional argument (which is Include)
includeValue = value;
}Issue: If there are multiple positional arguments (e.g., Suggestion: Consider only processing the first positional argument or documenting this behavior. 2. Record.Exception - Missing Block Body HandlingIn if (body is BlockSyntax block)
{
// If it's a single statement block, extract the statement
if (block.Statements.Count == 1)
{
return block.Statements[0];
}
// Otherwise return the block as-is (will need to be a compound statement)
return block;
}Issue: When returning the block directly for multi-statement lambdas, it's placed inside the try block as a nested block: try
{
{ // Extra braces here
statement1;
statement2;
}
}Suggestion: When if (actionBody is BlockSyntax blockBody && blockBody.Statements.Count > 1)
{
// Use block's statements directly
tryBodyStatement = SyntaxFactory.Block(blockBody.Statements)...
}3. Record.ExceptionAsync - Missing Async/Await VerificationIn // If async, we may need to await the action
if (isAsync && tryBodyStatement is ExpressionStatementSyntax exprStmt)
{
var awaitExpr = SyntaxFactory.AwaitExpression(...);Issue: This blindly adds Suggestion: Consider using semantic analysis to check if the expression is actually awaitable, or document that this migration assumes correct XUnit usage. 4. Platform Attribute - Case SensitivityIn return nunitPlatform.ToLowerInvariant() switch
{
"win" or "win32" or ... => "Windows",Minor: NUnit's platform matching is case-insensitive, so this is correct. However, consider adding a comment explaining this matches NUnit's behavior, as it's not immediately obvious why we're lower-casing. 5. Test Coverage - Missing Edge CasesThe tests cover basic scenarios well, but consider adding tests for:
Verdict✅ APPROVE - No critical issues The implementation is solid and follows TUnit conventions well. The suggestions above are optional improvements for edge cases and code robustness, but not blocking issues. |
Summary
This PR addresses several migration code fixer issues:
Record.Exception()pattern to try-catch blocksAssert.Throws<T>()exception property access (already working)[Platform]attribute not handled #4339: Convert NUnit[Platform]attribute to TUnit[RunOn]/[ExcludeOn]Changes
xUnit Record.Exception() Conversion (#4332)
Converts the xUnit pattern:
To:
xUnit Exception Property Access (#4334)
Added tests verifying that
Assert.Throws<T>()with property access works correctly:.ParamNameAssert.Containswithex.MessageNUnit [Platform] Conversion (#4339)
Instead of removing the NUnit
[Platform]attribute, converts to TUnit equivalents:[Platform(Include = "Win")]→[RunOn(OS.Windows)][Platform(Exclude = "Linux")]→[ExcludeOn(OS.Linux)][Platform(Include = "Win,Linux")]→[RunOn(OS.Windows | OS.Linux)]Supported platform mappings:
Test plan
🤖 Generated with Claude Code